package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"

	"hello_server/pb"
	"google.golang.org/grpc/health"
	healthpb "google.golang.org/grpc/health/grpc_health_v1"
	"github.com/hashicorp/consul/api"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
)

type server struct {
	pb.UnimplementedHelloServer
}

//确保server结构体实现了pb.HelloServer接口
// var _ pb.HelloServer = &server{}
var _ pb.HelloServer = (*server)(nil)


func (s *server) SayHello(ctx context.Context, in *pb.Request) (*pb.Response, error) {
	// 从客户端读取metadata.
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil, status.Errorf(codes.DataLoss, "UnarySayHello: failed to get metadata")
	}
	if t, ok := md["timestamp"]; ok {
		fmt.Printf("timestamp from metadata:\n")
		// []string
		for i, e := range t {
			fmt.Printf(" %d. %s\n", i, e)
		}
	}
	return &pb.Response{
		Reply: "hello " + in.Name,
	}, nil
}


func main() {
	lis, err := net.Listen("tcp", ":8081")
	if err != nil {
		log.Fatalf("net.Listen failed, err:%v\n", err)
	}
	//创建 grpc 服务
	s := grpc.NewServer()

	//健康检查注册
	healthcheck := health.NewServer()
	healthpb.RegisterHealthServer(s, healthcheck)

	//注册grpc服务
	pb.RegisterHelloServer(s, &server{})
	log.Println("server start...")
	go func ()  {
		if err := s.Serve(lis); err != nil {
		log.Fatalf("s.Serve failed, err:%v\n", err)
		}
	}()

	// 1. 连上consul
	client, err := api.NewClient(api.DefaultConfig())
	if err != nil {
		log.Fatalf("api.NewClient failed, err:%v\n", err)
	}
	//健康检查
	check := &api.AgentServiceCheck{
		GRPC: "192.168.233.129:8081", //玩网IP和端口
		Timeout: "10s", //超时时间
		Interval: "10s",//每隔10秒检查一次
		DeregisterCriticalServiceAfter: "20s", //注销不健康的服务
	}
	// 2. 服务注册
	srv := &api.AgentServiceRegistration{
		ID:      "hello-server-8081", // 服务名称-ip-端口
		Name:    "hello",
		Tags:    []string{"hello"},
		Address: "127.0.0.1",
		Port:    8081,
		Check:   check, //调用变量check
	}
	client.Agent().ServiceRegister(srv)

	// 3. 注销服务
	quitChan := make(chan os.Signal,1)
	// syscall.SIGTERM(kill), syscall.SIGINT(Ctrl+C), syscall.SIGKILL(Kill -9)
	signal.Notify(quitChan, syscall.SIGTERM, syscall.SIGINT)
	<-quitChan // hang住
	fmt.Println("嘿嘿嘿")
	client.Agent().ServiceDeregister("hello-server-8081") // 从consul中注销服务
}
